//
//  ZZIAPHelper.m
//  zz-IAPHelper
//
//  Created by ZengLiZhi on 2024/4/3.
//

#import "ZZIAPHelper.h"
#import <objc/runtime.h>

@implementation SKProductsRequest (ZZIAP)

- (void)setZz_request:(ZZIAPRequest *)zz_request{
    objc_setAssociatedObject(self, @selector(zz_request), zz_request, OBJC_ASSOCIATION_RETAIN);
}

- (ZZIAPRequest *)zz_request{
    return objc_getAssociatedObject(self, _cmd);
}

@end

@implementation SKPayment (ZZIAP)

- (void)setZz_request:(ZZIAPRequest *)zz_request{
    objc_setAssociatedObject(self, @selector(zz_request), zz_request, OBJC_ASSOCIATION_RETAIN);
}

- (ZZIAPRequest *)zz_request{
    return objc_getAssociatedObject(self, _cmd);
}

@end

@interface ZZIAPHelper ()<SKProductsRequestDelegate, SKPaymentTransactionObserver>



@end

@implementation ZZIAPHelper

+ (instancetype)sharedInstance {
    static ZZIAPHelper *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[ZZIAPHelper alloc] init];
    });
    return sharedInstance;
}

- (ZZIAPHander *)iapHander{
    if (!_iapHander) {
        _iapHander = [[ZZIAPHander alloc] init];
    }
    return _iapHander;
}

- (instancetype)init{
    self = [super init];
    if (self) {
        _userId = @"ZZIAPRequest_";
        _restoreSuccessTip = @"恢复购买成功";
        _restoreEmptyTip = @"暂无可恢复的内购项目";
        // 购买监听写在程序入口,程序挂起时移除监听,这样如果有未完成的订单将会自动执行并回调 paymentQueue:updatedTransactions:方法
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    }
    return self;
}


- (void)dealloc {
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

- (NSString *)storageKey:(NSString *)productId{
    NSString *key = [NSString stringWithFormat:@"%@%@", self.userId, productId];
    NSLog(@"storageKey : %@",key);
    return key;
}
#pragma mark - 支付入口
- (void)request:(ZZIAPRequest *)request{

    if ([SKPaymentQueue canMakePayments]) {
        //创建业务订单
        [request creatOrder:^(ZZIAPRequest * _Nonnull request, NSString * _Nonnull orderId) {
            if (!request.orderId) {
                request.orderId = orderId;
            }
            [self requestProductInfo:request];
            // 本地保存订单编号orderId
            [[NSUserDefaults standardUserDefaults] setObject:orderId forKey:[self storageKey:request.productId]];
            [[NSUserDefaults standardUserDefaults] synchronize];
        }];
    }else{
        [self.iapHander handleCode:ZZIAPRequestCode_NotAllow];
        if (request.completion) {
            request.completion(request,ZZIAPRequestCode_NotAllow,nil);
        }
    }
}

//获取购买项目的ProductInfo
- (void)requestProductInfo:(ZZIAPRequest *)request{
    NSSet *nsset = [NSSet setWithArray:@[request.productId]];
    SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
    productsRequest.delegate = self;
    productsRequest.zz_request = request;
    [productsRequest start];
}

#pragma mark - SKProductsRequestDelegate

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
    NSArray *products = response.products;
    ZZIAPRequest *zzRequest = request.zz_request;
    
    //匹配当前支付的项目
    SKProduct *product = nil;
    for (SKProduct *pro in products) {
        if ([pro.productIdentifier isEqualToString:zzRequest.productId]) {
            product = pro;
            break;
        }
    }
    
    if (product) {
        //项目加入购买队列
        SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product];
        payment.applicationUsername = [NSString stringWithFormat:@"%@_%@",zzRequest.payType,zzRequest.orderId];
        payment.zz_request = zzRequest;
        [[SKPaymentQueue defaultQueue] addPayment:payment];
    }else{
        //没有匹配到相应的内购项目
        [self.iapHander handleCode:ZZIAPRequestCode_NoProduct];
        if (zzRequest.completion) {
            zzRequest.completion(zzRequest,ZZIAPRequestCode_NoProduct,products);
        }
    }
}

//请求失败
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
#if DEBUG
    NSLog(@"------------------错误-----------------:%@", error);
#endif
}
 
- (void)requestDidFinish:(SKRequest *)request{
#if DEBUG
    NSLog(@"------------反馈信息结束-----------------");
#endif
}

#pragma mark - Restore
//恢复购买
- (void)restorePurchases{
    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}

- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
    if (queue.transactions.count < 1) {
        if (self.restoreCompletion) self.restoreCompletion(ZZIAPRequestCode_RestoredEmpty,nil);
    } else {
        if (self.restoreCompletion) self.restoreCompletion(ZZIAPRequestCode_RestoredSuccess,nil);
    }
}

- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {
    if (self.restoreCompletion) self.restoreCompletion(ZZIAPRequestCode_RestoredFailed,nil);
}

#pragma mark - SKPaymentTransactionObserver

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {
    
    for (SKPaymentTransaction *transaction in transactions) {
        
        SKPayment *payment = transaction.payment;
        BOOL isRestore = payment.zz_request == nil;
        
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchasing://购买中
                break;
            case SKPaymentTransactionStatePurchased://支付成功
            {// 收据发送到服务器
                NSString *transferId = transaction.transactionIdentifier;
                if (transferId.length == 0) {
                    return;
                }
                
                NSString *payType = @"ZZIAPDefaultPayType";
                NSString *orderId = @"ZZIAPDefaultOrderId";
                
                if (payment.applicationUsername.length > 0) {
                    NSArray *arr = [payment.applicationUsername componentsSeparatedByString:@"_"];
                    if (arr.count == 2) {
                        payType = arr.firstObject;
                        orderId = arr.lastObject;
                    }
                }
                
                NSData *receiptData = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]];
                NSString *receiptStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
                
                //发送验证
                [self.iapHander sendReceiptToServerWithPayType:payType isRestore:isRestore orderId:orderId receiptStr:receiptStr transactionIdentifier:transferId completion:^(BOOL isSuccess, NSString * _Nonnull orderId) {
                    if (isSuccess) {
                        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                    }
                }];
                
                break;
            }
            case SKPaymentTransactionStateFailed://购买失败
                if (transaction.error) {
                    NSLog(@"Transaction error: %@", transaction.error);
                }
                ZZIAPRequestCode code = ZZIAPRequestCode_Failed;
                if (transaction.error.code == SKErrorPaymentCancelled) {
                    //购买取消
                    code = ZZIAPRequestCode_Cancel;
                }
                [self.iapHander handleCode:code];
                if (!isRestore) {
                    //购买流程
                    payment.zz_request.completion(payment.zz_request, code, transaction);
                }else{
                    //恢复流程
                    self.restoreCompletion(code, transaction);
                }
                //交易失败
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
            case SKPaymentTransactionStateRestored://重复购买
                if (!isRestore) {
                    //购买流程
                    payment.zz_request.completion(payment.zz_request, ZZIAPRequestCode_Restored, transaction);
                }else{
                    //恢复流程
                    self.restoreCompletion(ZZIAPRequestCode_Restored, transaction);
                }
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
            default:
                break;
        }
    }
}

@end

